package gui;

import com.teamdev.jxbrowser.Browser;
import com.teamdev.jxbrowser.BrowserFactory;
import com.teamdev.jxbrowser.events.NavigationEvent;
import com.teamdev.jxbrowser.events.NavigationFinishedEvent;
import com.teamdev.jxbrowser.events.NavigationListener;
import gui.graphicals.ClosableTabbedPane;
import gui.graphicals.ToolBar;
import java.awt.Point;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import navigator.NavigatorController;
import technical.ClInit;

/**
 * @author thomas, michael
 */
public class NavigatorView extends AbstractModule implements ActionListener, KeyListener, MouseListener, NavigationListener, ListSelectionListener, WindowListener {

    private static String __defaultHomePage = ClInit.getBrowserDefaultHomePage();
    private static int __tabMaxLenght = ClInit.getBrowserMaxTabLenght();     // Text lenght to show in a tab
    private static int __maxTab = ClInit.getBrowserMaxTabNumber();           // Maximum tab we can have
    
    private static Point _itemToDelete;
    public JFrame _favoritesFrame;
    private boolean _isFavoritesActive = false;
    private MainWindow _mainWindow;
    public JList _favoritesList;
    public static Vector<String> _vectorFavorites;
    public static Vector<String> _vectorHistory;
    private Browser _myNavigator;
    private Browser _myBrowsers[];
    private JTextField _myLinkField;
    private JTabbedPane _myMainFrame;
    private NavigatorController _navigatorController;
    private static final long serialVersionUID = -2408484785384185177L;

    public NavigatorView(MainWindow mainWindow) {
        super(mainWindow);
        _mainWindow = mainWindow;
    }

    @Override
    protected ToolBar getToolBar() {

        ToolBar tb = new ToolBar();
        ActionListener myActList = this;

        tb.makeButton("back.png",
                "BACK",
                "Retour en arrière",
                "BACK",
                myActList);

        tb.makeButton("forward.png",
                "FORWARD",
                "Continue la navigation",
                "FORWARD",
                myActList);


        tb.addSeparator();

        tb.makeButton("refresh.png",
                "REFRESH",
                "Rafraichir la page",
                "REFRESH",
                myActList);

        tb.addSeparator();

        tb.makeButton("history.png",
                "HISTORY",
                "Accéder à l'historique",
                "HISTORY",
                myActList);

        tb.makeButton("favorite.png",
                "FAVORITE",
                "Accéder aux favoris",
                "FAVORITE",
                myActList);

        tb.addSeparator();

        tb.makeButton("home.png",
                "HOME",
                "Aller a la page d'accueil",
                "HOME",
                myActList);

        _myLinkField = new JTextField(__defaultHomePage);
        _myLinkField.addKeyListener(this);
        tb.add(_myLinkField);

        tb.makeButton("go.png",
                "GO",
                "C'est parti",
                "GO",
                myActList);

        return tb;
    }

    @Override
    protected JTabbedPane getMainFrame() {

        _myMainFrame = new ClosableTabbedPane();
        Browser nav = getNavigator();
        _myMainFrame.addTab(nav.getTitle(), nav.getComponent());

        _myMainFrame.addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent ce) {
                ClosableTabbedPane source = (ClosableTabbedPane) ce.getSource();
                Browser nav = getBrowser(source.getSelectedIndex());
                try {
                    _myLinkField.setText(nav.getCurrentLocation());
                } catch (NullPointerException ex) {
                    _myLinkField.setText(__defaultHomePage);
                    System.err.println("NullPointerException rencontré ici\n"
                            + "Cela se produit quand on sélectionne le premier onglet crée à l'initialisation du navigateur");
                }

            }
        });

        return _myMainFrame;
    }

    private Browser getNavigator() {

        _myNavigator = BrowserFactory.createBrowser();
        _myNavigator.navigate(__defaultHomePage);
        _myNavigator.waitReady();

        _myBrowsers = new Browser[__maxTab];
        _myBrowsers[0] = _myNavigator;
        
        _navigatorController = NavigatorController.getInstance();
        _navigatorController.addPage(_myNavigator, 0);
        
        _myNavigator.addNavigationListener(this);

        _vectorFavorites = new Vector<String>();
        // Reading the favorites' file
        /********************************************************************/
        BufferedReader bfFavorites = null;
        try {
                bfFavorites = new BufferedReader(new FileReader("favorites.txt"));
                String line = "";
                try {
                    line = bfFavorites.readLine();
                    while (line != null) {
                        _vectorFavorites.add(line.toString());
                        line = bfFavorites.readLine();
                    }
                    bfFavorites.close();
                }
                catch (IOException ex) {
                    Logger.getLogger(NavigatorView.class.getName()).log(Level.SEVERE, null, ex);
                }
        }
        catch (FileNotFoundException error) {
                // si le fichier n'existe pas, j'affiche un message d'erreur
                System.err.println(error);
                // et on sort
                System.exit(1);
        }
        /********************************************************************/
        
        _vectorHistory = new Vector<String>();
        // Read the history file
        /********************************************************************/
        BufferedReader bfHistory = null;
        try {
                bfHistory = new BufferedReader(new FileReader("history.txt"));
                String line = "";
                try {
                    line = bfHistory.readLine();
                    while (line != null) {
                        _vectorHistory.add(line.toString());
                        line = bfHistory.readLine();
                    }
                    bfHistory.close();
                }
                catch (IOException ex) {
                    Logger.getLogger(NavigatorView.class.getName()).log(Level.SEVERE, null, ex);
                }
        }
        catch (FileNotFoundException error) {
                // si le fichier n'existe pas, j'affiche un message d'erreur
                System.err.println(error);
                // et on sort
                System.exit(1);
        }
        /********************************************************************/
        
        return _myNavigator;

        /*
        _myNavigator =
        new JEditorPane();
        _myNavigator.setEditable(false);
        
        try {

            _myNavigator.setPage(new URL(_defaultHomePage));
            _myNavigator.addHyperlinkListener(new HyperlinkListener() {

                @Override
                public void hyperlinkUpdate(HyperlinkEvent e) {
                    if (e.getEventType()
                            == HyperlinkEvent.EventType.ACTIVATED) {
                        URL url =
                                e.getURL();
                        if (url
                                == null) {
                            return;
                        }

                        try {
                            _myNavigator.setPage(url);
                        } catch (IOException ex) {
                            Logger.getLogger(NavigatorView.class.getName()).log(Level.SEVERE,
                                    null,
                                    ex);
                        }
                    }
                }
            });

        } catch (IOException ex) {
        Logger.getLogger(NavigatorView.class.getName()).log(Level.SEVERE,
        null,
        ex);
        }
        
        }
        }
        });
        
        } catch (IOException ex) {
        Logger.getLogger(NavigatorView.class.getName()).log(Level.SEVERE,
        null,
        ex);
        }
        
        _myNavigator.add(new JLabel("Google"));
        return _myNavigator;
         */
    }

    /*
     * Return the Browser depends of the tab index
     */
    private Browser getBrowser(int index) {
        if (index < 0 || index > __maxTab) {
            index = 0;
        }

        Browser nav;
        try {
            nav = _myBrowsers[index];
        } catch (NullPointerException ex) {
            nav = _myBrowsers[0];
        }

        return nav;
    }

    /**
     * thomas :
     * creation de ces methodes pour ajouter un onglet avec choix d'onglet actif ou non
     * @param url
     */
    public void addTab(String url) {
        addTab(url, true);
    }

    public void addTab(String url, boolean goTo) {

        Browser nav = BrowserFactory.createBrowser();
        nav.navigate(url);
        nav.waitReady();
        nav.addNavigationListener(this);

        // Build title with correct lenght 
        String title = nav.getTitle();
        
        if (title.length() > __tabMaxLenght) {
            title = title.substring(0, __tabMaxLenght) + "...";
        }

        // Show title page in new tab and add the component
        _myMainFrame.addTab(title + "    ", null, nav.getComponent(), nav.getTitle());

        int newIndex = _myMainFrame.getTabCount() - 1;
        _myBrowsers[newIndex] = nav;
        _navigatorController.addPage(nav, newIndex);

        // If wanted, go on new tab and update link in text field
        if (goTo) {
            _myLinkField.setText(url);
            _myMainFrame.setSelectedIndex(newIndex);
        }
    }
    
    /*
     * Return the current Browser depends of the selected tab
     */
    public Browser getSelectedBrowser() {
        Browser _currentBrowser = _myBrowsers[_myMainFrame.getSelectedIndex()];
        return _currentBrowser;
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        Browser selectedNav = getBrowser(_myMainFrame.getSelectedIndex());

        if (e.getActionCommand().equalsIgnoreCase("GO")) {
            selectedNav.navigate(_myLinkField.getText());
            selectedNav.waitReady();
            _myLinkField.setText(selectedNav.getCurrentLocation());
        }

        if (e.getActionCommand().equalsIgnoreCase("BACK")) {
            if (selectedNav.canGoBack()) {
                selectedNav.goBack();
                selectedNav.waitReady();
                _myLinkField.setText(selectedNav.getCurrentLocation());
            }
        }

        if (e.getActionCommand().equalsIgnoreCase("FORWARD")) {
            if (selectedNav.canGoForward()) {
                selectedNav.goForward();
                selectedNav.waitReady();
                _myLinkField.setText(selectedNav.getCurrentLocation());
            }
        }

        if (e.getActionCommand().equalsIgnoreCase("REFRESH")) {
            selectedNav.refresh();
            selectedNav.waitReady();
            _myLinkField.setText(selectedNav.getCurrentLocation());
        }

        if (e.getActionCommand().equalsIgnoreCase("HOME")) {
            selectedNav.navigate(__defaultHomePage);
            _myLinkField.setText(__defaultHomePage);
            selectedNav.waitReady();
            _myLinkField.setText(selectedNav.getCurrentLocation());
        }

        if (e.getActionCommand().equalsIgnoreCase("HISTORY")) {

            String history = "Historique : <br /><br />";

            Browser _myHistory = BrowserFactory.createBrowser();
            
            for (String hist : _vectorHistory) {
                if (!hist.equalsIgnoreCase("")) {
                    history += hist + "<br />";
                }
            }
            
             _myMainFrame.addTab("Historique", _myHistory.getComponent());

            int newIndex = _myMainFrame.getTabCount() - 1;
            _myBrowsers[newIndex] = _myHistory;
            _navigatorController.addPage(_myHistory, newIndex);

            _myLinkField.setText("Historique");
            _myMainFrame.setSelectedIndex(newIndex);
            _myHistory.setContent(history);
            
            _myHistory.addNavigationListener(this);
        }

        if (e.getActionCommand().equalsIgnoreCase("FAVORITE")) {
            
            if (!_isFavoritesActive) {
                _isFavoritesActive = true;
                
                _favoritesFrame = new JFrame("Favoris");
                _favoritesFrame.setSize(170, _mainWindow.getHeight() - 130);
                _favoritesList = new JList(_vectorFavorites);
                JScrollPane scrollPane = new JScrollPane(_favoritesList);
                _favoritesFrame.add(scrollPane);
                _favoritesFrame.setLocation(_mainWindow.getX() + _mainWindow.getWidth() - 180, _mainWindow.getY() + 120);
                _favoritesFrame.setVisible(true);
                _favoritesFrame.setAlwaysOnTop(true);

                _favoritesList.addListSelectionListener(this);
                _favoritesList.addMouseListener(this);
                _favoritesFrame.addWindowListener(this);
            }
            else {
                _favoritesFrame.dispose();
                _isFavoritesActive = false;
            }
        }
        
        if (e.getActionCommand().equalsIgnoreCase("Supprimer")) {
             int index = _favoritesList.locationToIndex(_itemToDelete);
            _vectorFavorites.remove(index);
            _favoritesList.repaint();
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == 10) {
            getSelectedBrowser().navigate(_myLinkField.getText());
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

    @Override
    public void navigationStarted(NavigationEvent ne) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void navigationFinished(NavigationFinishedEvent nfe) {
        _myLinkField.setText(getSelectedBrowser().getCurrentLocation());
        
        String title = getSelectedBrowser().getTitle();
        
        if (title.length() > __tabMaxLenght) {
            title = title.substring(0, __tabMaxLenght) + "...    ";
        }
        
        // Register the page in the history file
        if (!getSelectedBrowser().getCurrentLocation().equalsIgnoreCase("")) {
            
            Date date = new Date();
            SimpleDateFormat formatDate = new SimpleDateFormat("dd/MM/yyyy H:m:s");
            System.out.println(formatDate.format(date));
            String histo = " -> " + getSelectedBrowser().getCurrentLocation() + " (" + formatDate.format(date) + ")";
            _vectorHistory.add(histo);
        }
        
        // Problème de rafraichissement du JtabbedPane (largeur ne se met pas à la taille du titre
        // Problème lors du chargement de Youtube -> A voir...
        _myMainFrame.setTitleAt(_myMainFrame.getSelectedIndex(), title);
        _myMainFrame.setMnemonicAt(_myMainFrame.getSelectedIndex(), title.length());
        _myMainFrame.setDisplayedMnemonicIndexAt(_myMainFrame.getSelectedIndex(), title.length());
        _myMainFrame.setToolTipTextAt(_myMainFrame.getSelectedIndex(), getSelectedBrowser().getTitle());
        _myMainFrame.repaint();
    }

    @Override
    public void valueChanged(ListSelectionEvent e) {
        int index = _favoritesList.getSelectedIndex();
        getSelectedBrowser().navigate(_vectorFavorites.elementAt(index));
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        if (e.getButton() == 3) {
            
            JPopupMenu contextMenu = new JPopupMenu();
            JMenuItem supprimer = new JMenuItem("Supprimer");
            contextMenu.add(supprimer);
            contextMenu.show(_favoritesList, e.getX(), e.getY());
            
            _itemToDelete = e.getPoint();
            supprimer.addActionListener(this);
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void mouseExited(MouseEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void windowOpened(WindowEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void windowClosing(WindowEvent e) {
        _isFavoritesActive = false;
    }

    @Override
    public void windowClosed(WindowEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void windowIconified(WindowEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void windowDeiconified(WindowEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void windowActivated(WindowEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void windowDeactivated(WindowEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }
}
